﻿using Devil;

namespace GameToolkit.BehaviourTree
{
    public static class BehaviourTreeUtils
    {
#if UNITY_EDITOR
        //bool OpenAsset(BehaviourTreeAsset asset, bool newWindow)
        public static System.Action<BehaviourTreeAsset, bool> OpenAsset { get; internal set; }
        public static System.Action<BehaviourTreePlayer, bool> OpenPlayer { get; internal set; }
        public static GetterDelegate<BehaviourTreePlayer, bool> IsDebugingPlayer { get; internal set; }
#endif

        public static T GetDecorator<T>(this ExecutableEntry node) where T : Decoration
        {
            var len = node == null ? 0 : node.DecoratorCount;
            for (int i = 0; i < len; i++)
            {
                if (node.GetDecorator(i) is T t)
                    return t;
            }
            return null;
        }

        /// <summary>
        /// 在父节点中查找装饰节点
        /// </summary>
        /// <param name="node"></param>
        /// <param name="filter"></param>
        /// <param name="findIntoParentTree"></param>
        /// <returns></returns>
        public static Decoration FindDecoratorInParents(this ExecutableEntry node, FilterDelegate<Decoration> filter, BehaviourTreePlayer findIntoParentTree = null)
        {
            var item = node;
            var pl = findIntoParentTree;
            while (item != null)
            {
                var len = item.DecoratorCount;
                for (int i = 0; i < len; i++)
                {
                    var decor = item.GetDecorator(i);
                    if (filter == null || filter(decor))
                        return decor;
                }
                item = item.Parent;
                if (item == null && pl != null)
                {
                    item = pl.ParentEntry;
                    pl = pl.Parent;
                }
            }
            return null;
        }

        public static T FindDecoratorInParents<T>(this ExecutableEntry node, BehaviourTreePlayer findIntoParentTree = null) where T : class
        {
            var item = node;
            var pl = findIntoParentTree;
            while (item != null)
            {
                var len = item.DecoratorCount;
                for (int i = 0; i < len; i++)
                {
                    var decor = item.GetDecorator(i);
                    if (decor is T t)
                        return t;
                }
                item = item.Parent;
                if (item == null && pl != null)
                {
                    item = pl.ParentEntry;
                    pl = pl.Parent;
                }
            }
            return null;
        }

        public static ExecutableEntry FindEntryInParents(this ExecutableEntry node, FilterDelegate<ExecutableEntry> filter, BehaviourTreePlayer findIntoParentTree = null)
        {
            var item = node;
            var pl = findIntoParentTree;
            while (item != null)
            {
                if (filter(item))
                    return item;
                item = item.Parent;
                if (item == null && pl != null)
                {
                    item = pl.ParentEntry;
                    pl = pl.Parent;
                }
            }
            return null;
        }

        public static T FindEntryInParents<T>(this ExecutableEntry node, BehaviourTreePlayer findIntoParentTree = null) where T : class
        {
            var item = node;
            var pl = findIntoParentTree;
            while (item != null)
            {
                if (item is T result)
                    return result;
                item = item.Parent;
                if (item == null && pl != null)
                {
                    item = pl.ParentEntry;
                    pl = pl.Parent;
                }
            }
            return null;
        }
    }
}
